perm filename ISSUES.1[COM,LSP]1 blob
sn#713506 filedate 1983-05-28 generic text, type C, neo UTF8
COMMENT ā VALID 00002 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 ā26-May-83 2227 STEELE@CMU-CS-C Comments on LASER.UPDATE
C00136 ENDMK
Cā;
ā26-May-83 2227 STEELE@CMU-CS-C Comments on LASER.UPDATE
Received: from CMU-CS-C by SU-AI with TCP/SMTP; 26 May 83 22:23:57 PDT
Received: ID <STEELE@CMU-CS-C>; 27 May 83 01:23:14 EDT
Date: 27 May 83 01:23:14 EDT
From: STEELE@CMU-CS-C
Subject: Comments on LASER.UPDATE
To: moon%scrc-tenex@MIT-MC, dlw%scrc-tenex@MIT-MC, declisp@CMU-CS-C,
fahlman@CMU-CS-C, vanroggen@CMU-CS-C, rpg@SU-AI,
guy.steele@CMU-CS-A
Here follows an annotated version of the file from MOON and DLW.
My comments are in braces. Most of it is well under control, but
there remain controversial issues as always.
--Guy
---------------------------------------------------------
File [CMU-CS-C]PRVA:<SLISP.SCL>LASER.REPLY
This file is a reply in the form of an annotated copy of LASER.UPDATE.
Annotations by Steele are in braces. Standard comments include:
{controversial} Requires more discussion, or is being discussed.
I don't want to decide this unilaterally.
{will fix} I will fix this (in some cases, have already fixed it).
{okay by me} This looks good, but I'd like confirmation.
{will clarify} I will improve the prose (or have already improved it).
This file contains comments on the Laser edition of the Common Lisp manual.
* means this is non-trivial or controversial.
[done] means this has been fixed in the latest (mid-May) version of the manual.
[not done] means it hasn't been.
[new] means this is a new comment on text not in the Laser manual.
[gloss] is new commentary resulting from new text not in the Laser manual.
Major issues are summarized at the end.
* 0: (everywhere) Why are there so many type-predicates? typep could just
as well be used, and has the advantage that you don't have to remember for
a hundred things whether each one is spelled "foop" or "foo-p". Why doesn't
the "setf argument" apply to type predicates as much as to storing functions? -- Moon
{controversial}
9: |P 1: 'consititutes' -- Moon [not done]
{now done}
14: |P 4: says erroneously that a decimal point is required. The BNF and
the examples are consistent and correct. -- Moon [done]
15: |P 1: the default value is 'single-float', not 'single'. -- Moon [done]
15: disagrees with p.34 about whether the type is (complex t1) or (complex t1 t2).
Also the eql identities on p. 15 prohibit floating-point contagion between the
real and imaginary parts, which might be both useful to the implementation and
numerically valuable. I.e. (complex 1/3 0.5) could not float the 1/3. -- Moon [not done]
{On page 34 it is noted that (complex x) is defined to mean the same
thing as (complex x x). Will clarify.}
* 17: |P 5: do not include ! and ? in the list of alphabetics, since they are
reserved to the user. They default to alphabetic but are likely to be changed. -- Moon
[done]
18: Neither the text nor the examples shows that \ before a letter suppresses
case-conversion. Both should. -- Moon [done]
* 19: |P 4: If most functions advertised to work on lists will work on dotted
lists, then no one calls the ENDP predicate. I've complained about this before.
Possibly the right thing is to avoid the word "list" here, and add an explicit
discussion of the distinction between trees and sequences.
Which way is our policy? -- Moon
[done]
[gloss] The data type chapter now says that functions advertised to work
on lists require true lists, and whether they behave reasonably when
given a dotted list depends on the implementation. So I guess this means
they are allowed to do any damned thing they please. We will error on
dotted lists either by using ENDP or by virtue of our full-error-checking
CDR instruction.
19: In the second example, change "a list of three" to "a dotted list
of three"; in this context it is important to make the distinction. -- DLW [done]
20: The last line uses the term S-expression. I belive we have formally
agreed to abandon this term; I really don't like it, and you don't even
explain it anywhere. "a one-dimensional array of Lisp objects" should
be used instead. -- DLW [done]
20: |P 2: 'in in' -> 'is in' -- Moon [done]
21: The last sentence of section 2.5.2 ("this syntax") is a non-sequitur,
put it in a different paragraph (not necessarily its own separate one). -- Moon [done]
* 21-22: Be specific about the order in which the character are stored
into the string, and that the bits are stored into the bit string,
particularly the latter. Is (aref #*10110 0) zero or one? -- DLW [done]
22: S 2.10: 'Nearly all function' -- Moon [done]
25: 'hash-table' but 'readtable'. I guess it's too late to try to regularize
everything. -- Moon
{Yep, that bugs me too. Too late.}
25: you imply that no new subtypes will ever be added to 'common'. The right
thing to say is that no implementation may unilaterally add subtypes to common,
however future extensions to the Common Lisp manual may. Also you defined
it in such a way that (array t) and (complex t t) are not subtypes of common!
This was clearly not what you meant to say. (In fact, if you think about it
more the one essential difference between Lisp and Ada (or Pascal) is that in
Lisp it is meaningful for (array t) to be a subtype of common although t itself
is not. Well, there are about two other essential differences...) -- Moon [done]
* 25: allow package to be a subtype of hash-table (although it won't be in
ours, most likely) -- Moon [not done]
{In my opinion this is a bad idea.}
27: this section is very confusing because it isn't made perfectly clear that
'entities' includes both 'names' and 'objects'. Covering both in one set of
rules is nice, but they are really very different. Also you need a note
pointing out that parallelism is not addressed by this standard and implementations
that add extensions for parallel processing with shared objects (this could be
coroutines, multiple processes with asynchronous process switching, or
multiple hardware processors) will have to define for themselves what dynamic
extent and dynamic scope mean. In the Lisp machine dynamic extent means what
the first sentence in your definition says, while dynamic scope means dynamic
extent and usually indefinite scope -within- a single process, although there
are constructs (LET-GLOBALLY) where it means indefinite scope across all processes.
But an S-1 multiprocessor would have real trouble confining scope of some things
to a single process. -- Moon [not done]
{Will clarify and add examples.}
28: The compose example won't work. You need "funcall" in two places.
Sorry, this isn't Scheme... -- DLW [done]
29: |P 3: 'possibility is shadowing' -- Moon [done]
* 29: Are special variable bindings captured by function closures? Does it
make a difference whether the closure has been passed "upward" out of the
dynamic extent of the binding? In Sussman's "unwind-protect" semantics,
special bindings are not captured by function closures, which seems like
a fatal crock from the user point of view ("why should declaring a variable
special make it disappear completely?") On the other hand, if function closures
do capture special bindings when used "downward", undesired behavior can
occur. Since upward funargs are a new language feature, I think it is best
not to capture special bindings. This is what your current text implies, but
you need to be explicit about this, even though I don't think your
conceptual structure in this chapter can express the distinction. In any case,
catches (which also have dynamic scope) should -not- be captured by closures! -- Moon
[not done]
{It is intended that specials not be captured. A careful reading of
Chapter 3 will produce this information: special bindings have dynamic
extent, period; therefore they cannot be captured. Examples and additional
clarification will be added.}
* 32: keyword should be a subtype of symbol; this would often be used with
typecase. -- Moon [not done]
{okay by me}
32: Table 4-1 is in the wrong place. Also I think you should flush the cute
but non-obvious order and alphabetize it. -- Moon [not done]
{okay by me}
* 32: Re the query: Yes, it should be defined to be in the obvious
order, rather than left to the implementation, for the reason you say. -- DLW [not done]
{okay by me}
* 32: (the query about and/or type expressions). The last sentence on p.31 says
that these predicates should not have side-effects, however as you point out
errors are side-effects. People will expect the and/or type expressions to
have the same evaluation rules as the and/or special forms, and that is easy
to do and useful, so I think it should be done. If not, the type expressions
should be renamed to intersection and union to avoid the implication from and/or. -- Moon
[not done]
{okay by me}
* 33: Since "typep" means "can the array ONLY hold this type", is there
a way to ask "is the array CAPABLE of holding this type", which would
return T for both A and B? I brought this up last time but can't
remember if I ever got an answer. -- DLW [not done]
{To ask "can array A hold an element of type B?" say
(subtypep B (array-element-type A))
This is the precise reason that array-lement-type was introduced.}
33: The text should explicitly say what "*" means; you shouldn't hear
about it in the examples first! Also say explicitly somewhere that the
lists are allowed to be shorter: that is, a vector type spec is (VECTOR
<element-type> <size>), but (VECTOR T) is OK even though it does NOT fit
into that pattern. Say it in the text, not just in the examples; this
is a language definition. -- DLW [not done]
{It is stated in |P 3 on page 31. This paragraph should be broken
out into a separate section and expanded upon.}
* 33: So what is the difference between (ARRAY *) and (ARRAY T)? Why is
it a subset? Please elaborate on this point, in the manual. -- DLW [not done]
{okay by me}
36: In the definition line, "lambda-list" => "varlist". (Page 99 too.) -- DLW [done]
37: cute notes for coerce: (coerce x t) <=> (identity x). (coerce x 'common)
means something but I can't figure out what. (coerce x nil)
is always an error (say more explicitly whether coerce signals an error). -- Moon [not done]
{okay by me}
* 37: What is the order of arguments to coerce? Once in the text you have
the type first; this may actually be the right thing, since most other functions
(except TYPEP) that take a type put it first, and the analogy with THE actually
makes a lot of sense. Also cross-reference THE here. -- Moon [not done]
{controversial}
* 38: Coercing of characters to integers should probably be allowed too. -- DLW [not done]
{controversial}
38: At the top of the page, what is ,=> ? -- DLW [not done]
{Typo; should be no comma.}
39: "S-expression" again. Use "Lisp object". -- DLW [done]
40: This section (5.1.2) really must explain the concept of an "unbound"
variable. -- DLW [not done]
{okay by me}
41: 'and' and 'or' can be defined in terms of 'cond', so why are they special
forms if 'cond' is a macro? If it's because the expansion into 'if' of the
form of 'cond' that 'or' turns into is incredibly clumsy, then 'cond' should
be a special form also. -- Moon [not done]
{I think this is partly a remnant of the discussion on multiple values.
Now that AND and OR have been clarified, I could go for making AND and OR
be macros, but making COND a special form would also be acceptable.}
* 41: The paragraph in the middle starting "an implementation" is vague.
It is never explained how one goes about providing an "equivalent macro
definition". What is the implementation restricted to do regarding, for
example, FSYMEVAL of special-form-naming symbols? This whole idea about
limiting the number of special forms and letting the implementation use
macros, but still be able to implement things as "quoted args"
functions, needs to be explained better, and the restrictions on the
result of FSYMEVAL need to be defined. -- DLW [not done]
{will clarify}
42: At the bottom, it should mention FLET too. -- DLW [not done]
{okay by me}
* 42: At the top, if "the expansion need not be.", then it is not clear
to me that one can write a portable code-walker, since it may run into
implementation-specific special forms! -- DLW [not done]
{I think we should limit this to forbid impl-dependent special forms
in this case. My intent was to permit impl-dependent functions.}
* 42: |P 1: It's useless to make most special forms be macros for the benefit
of program-understanding programs, so that those programs don't have to have
special knowledge of them, if the macros expand into implementation-dependent
code that those programs can't understand! This is especially bad when you
consider the omnipresence of SETF. I'm not sure what to do here, since it
is probably important to allow the macro expansion to be implementation dependent
for certain of these. -- Moon [not done]
{See previous remark.}
* 44: The rationale note: how so? If the compiler sees an arbitrary
form where it expects a keyword, well, how does it know that form
doesn't evaluate to a keyword symbol? Surely you aren't suggesting that
this be illegal? That would be no good at all. -- DLW [not done]
{In some situations type analysis will reveal that the arbitrary
form cannot produce a keyword. Simple example: a quoted expression
or number. For example, the compiler could catch (fill x y 0 5),
which should be (fill x y :start 0 :end 5).}
46: The value of 'x' is out of order in all the mixture examples -- Moon [done]
46: The examples of mixtures don't work. The bodies should be (list a b x c d)
to make them correct. -- DLW [done]
47: S-expression again. -- DLW [done]
48: The caveat about use at top level is given twice, inconsistently,
and only about DEFVAR and not the others. -- DLW [not done]
{will fix}
* 48: p.48 and p.79 disagree about whether DEFUN puts in a block named NIL
in addition to the block named the same as the function. Perhaps the mention
of RETURN on p.48 is just a typo. I could live with it either way. -- Moon [not done]
{will fix}
49: Re defconstant, you say "an error occurs". It is completely unclear
whether this means that "it is an error" or "an error is signalled".
Stick to your defined terminology. -- DLW [done]
49: The example is bad: in this case, DEFCONSTANT would be more
appropriate. Find something more variable. -- DLW [not done]
{will fix}
49: In eval-when's definition line, "situation" is in the wrong font. -- DLW [not done]
{will fix}
49: eval-when says that all top level forms are by default effectively wrapped in
(EVAL-WHEN (EVAL LOAD) ...). This isn't true; macro definitions and declarations,
and several other things one could list, happen at COMPILE time too. -- Moon [not done]
{will fix}
* 49: DEFCONSTANT claims to have an error (not to signal one?) if it is done
twice and the values aren't EQUALP. But EQUALP ignores alphabetic case. I
think this error check should be flushed; after all, DEFMACRO doesn't signal
an error if you redefine a macro to be something that generates different code.
Also use stars in the DEFVAR example.
Also add a note saying how to define a documented variable without giving it
a value (SETF of DOCUMENTATION I guess, bleagh). -- Moon [not done]
{Will fix. I guess I am content to not have an error check.
We never did some up with a good way to document without giving a value.
Maybe we really should go to a keyword syntax. Bawden, I think, noted that
"=" could be a keyword: (defvar x := 5 :documentation "foo") ???
But I think this is a bit too precious.}
51: [gloss] "p" vs "-p" rule for predicates documented.
51: I thought we voted to get rid of the term "pseudo-predicate". I
mentioned this last time. I guess I don't care, but I should point out
that you don't get much use out of this term in the rest of the manual. -- DLW [not done]
{will fix}
52: It says [NIL NIL, which appears to be a typo. -- DLW [done]
52: TYPEP shouldn't allow (VALUES ...) type specifiers, either. -- DLW [not done]
{will fix}
53: (TYPEP X '(CONS NULL)) is missing an "OR". You know, someone really
ought to run these examples... -- DLW [not done]
{will fix}
53: (under listp) '(cons null)' -> '(or cons null)' -- Moon [not done]
56: In the implementation note: "implemnetations" is a misspelling. -- DLW [done]
58: the nonexistent functions 'vref' and 'lessp' are used in two examples -- Moon [not done]
{will fix}
59: (and) <=> t, not just true, right? -- Moon [not done]
{okay by me}
62: In QUOTE, "the argument" should be @i[object]. It's misleading
to call it an argument, since it really isn't one. -- DLW [not done]
{will clarify}
63: Under symbol-function, it sounds like you can take what it returns and
pass it to macro-p and special-form-p. However, those functions are documented
to demand a symbol. Probably this is not a language problem, the manual just
needs to be clarified. -- Moon [not done]
{will clarify}
63: At the top, why does it say "(normally)"? I guess this means that
you might manually alter it? Probably "it is an error" to do so. -- DLW [not done]
{will clarify}
63: [gloss] macro-p renamed to macrop
64: In SETQ, you use the verb "assign to" backwards. The variable
is assigned; the value is not assigned. -- DLW [not done]
{will clarify}
65: FSET should be flushed with all the other update functions, in favor of
(SETF (SYMBOL-FUNCTION x) y). The word FSET could easily be confused
with SETF. --Benson [not done]
{will fix}
66-67: In the enumeration of legal SETF forms, you forget to
mention "anything done by DEFSETF". -- DLW [not done]
{will fix}
* 67: In SUBSEQ: is the replacement value restricted to be the same
length as the subsequence? Probably it should be. -- DLW [not done]
{will clarify}
68: In the SETF example, you don't even use G1 and G2 at all... -- DLW [done]
68: In SHIFTF, you might as well use the syntax {place}+ instead of
place {place}*, as long as you went to the trouble to define +. -- DLW [not done]
{will fix}
69: 'exchf' -> 'rotatef' -- Moon [done]
70: Moon's DEFSETF proposal [not done]
{okay by me}
70: rotatef in wrong font (at top of page) -- Moon [not done]
{will fix}
* 70: The documentation for defsetf is inconsistent about who is responsible
for ensuring proper order of evaluation. The text says that the defsetf body
is responsible for this, but the examples show SETF itself introducing
variables bound to all relevant things. Doing it the latter way is probably
better, because it makes it possible for macros such as PUSH to evaluate
arguments only once. But it requires that the implementation recognizes when
a variable is unnecessary and optimize it out (since it is impossible for the
defsetf body to do this itself), and requires you to resolve the issue of DEFSETF
on a special form (rather than a function), which is a reasonable thing to do
but introduces the need for the defsetf body to see actual pieces of the form,
rather than variables that are bound to the results of evaluating arguments of
the form. This is vital, but I don't have a suggested solution yet.
If you would put function specs into the language then you could document the
name of the function created by the complex form of DEFSETF, and then tools
such as TRACE could be used to debug it. -- Moon [not done]
{controversial}
* 71: (query) I think MMcM had a proposal about this. Need to check. -- Moon
* 71: The query: good problem. Make it legal to pass unknown keywords?? -- DLW
{controversial}
71: |P 2: 'arguments...consists'. -- Moon [not done]
{will fix}
* 71: Is APPLY's second argument required? What if you want to apply
something to no arguments? -- DLW [not done]
{will fix}
71: In the middle, "lista rgument" is a typo. -- DLW [done]
73: The syntax for LET and LET* is given twice, and one copy omits declarations -- Moon
[done]
73: In LET: you use both "varj" and "bodyj". In the Lisp Machine Manual,
we'd use "i" for one and "j" for the other, to clarify the fact that
they aren't don't have the same index set. -- DLW [not done]
{will clarify}
74: COMPILER-LET has to be a special form, not a macro, right? -- DLW [not done]
{will fix}
74: |P 5: 'let' -> 'let*' -- Moon [not done]
{will fix}
74: compiler-let cannot be written as a macro. It must be a special form. -- Moon [not done]
{will fix}
* 80: If 'loop' does not establish a block, then you must name it something
else, since it then cannot be extended into the full loop construct.
Also the rationale about loop vs tagbody is bogus, since a tagbody that
contains only one label and only one go, at the end, is easily recognized
(any time after macros have been expanded). -- Moon [not done]
{Okay, how about if the simple form establishes a block named NIL?}
80: In 7.8, when you say "All of the interaction constructs permit",
you should except LOOP. -- DLW [not done]
{See above.}
87: |P 4: 'A tag are' -- Moon [not done]
{will fix}
* 87: a tagbody that drops off the end should return the value(s) of the
last form, rather than nil, since many applications would otherwise need
to wrap a block around it; a simple looping construct that turns into -- Moon [not done]
(TAGBODY initialization NEXT iteration END return-value) is an example.
{Controversial. What is the value in the case
(TAGBODY form1 form2 tag) ? The value of form2, in the drop-through case?
What about when one does a GO to the tag?}
* 87: Make it very explicit that GO can be from an internal procedure,
and that you can GO through a catch. Can you GO from "under evaled
arguments" (that is, (list a b (go foo)), for example)? We should be
very explicit about this: don't try to hide the "dirty laundry" here,
because the result is that people will launch on implementation without
realizing important things about the run-time requirements. It's
important to keep the implementors in mind, when you're writing the
language definition. -- DLW [not done]
{Will clarify. There's already an example in chapter 3, but I'll add
cross-refs and more examples.}
89: |P 7: multiple-value-call and multiple-value-prog1 are receivers too. -- Moon [not done]
{will fix}
89: Document that (VALUES (FOO)) is the preferred way to ensure that exactly
one value is returned. -- Moon [done]
90: 'the the' -- Moon
{will fix}
91: (4th bullet) MULTIPLE-VALUE does not have an implicit PROGN. -- Moon [not done]
{will fix}
91: The list of implicit-progn functions should not include
multiple-value. -- DLW [not done]
{will fix}
* 91: In MULTIPLE-VALUE it is useful to have a way to discard unwanted values.
Since you aren't binding, using an ignored variable is inconvenient. The
Lisp machine uses NIL in place of a variable to mean "ignore this". For
consistency NIL should work in MULTIPLE-VALUE-BIND also, although it is
less essential there. -- Moon [not done]
{controversial}
* 93: Under CATCH it says that any Lisp object may be used as a tag, however
on page 94 it says that UNWIND-ALL uses NIL as a special-case flag. Thus
anything that throws to NIL, with an UNWIND-ALL between the throw and the
catch, will be screwed since the throw will not be relayed. I still maintain
that CATCH-ALL and UNWIND-ALL are worthless and should be flushed. -- Moon [not done]
{controversial}
93: CATCH deserves a compatibility note re Maclisp. -- DLW [not done]
{will clarify}
93: Hyphens are missing from CATCHALL. -- DLW [done]
94: Clarify that UNWIND-PROTECT protects against lexical exits (GO, RETURN,
and RETURN-FROM) as well as dynamic exits (THROW). -- Moon [not done]
{will clarify}
97: The syntax for MACRO is given twice, the two copies are inconsistent, and
both are wrong (neither includes documentation strings). This problem is
endemic in the special forms and should be fixed in a uniform and consistent
way. I suggest defining some abbreviations to be used in the function headers,
documenting them in the notation section, and using them consistently, and also
fixing all the fully-spelled-out syntax descriptions in the bodies of function
descriptions. For instance, you might make up a word such as 'dbody' that means
a body optionally preceded by documentation and declarations. Shades of Algol 68,
unfortunately. -- Moon [not done]
{will clarify}
97: S-expression again. -- DLW [done]
97: MACRO cannot be implemented as a macro, since it is the primitive for
defining macros and there is nothing for it to expand into. Unless it expands
into something outside the language, in which case it is useless for it to
be a macro rather than a special form. Compare my comment on p. 42. -- Moon [not done]
{It can expand into calls on implementation-dependent functions.}
99: lambda-list => varlist -- DLW [not done]
{will fix}
* 99: "destructuring" defmacro is essential! The reason the argument about
paralleling defun is utterly bogus is that destructuring defmacro is used when
defining special forms, whereas defun is for defining functions. It is quite
desirable for special forms to use parenthesization in their syntax. Enhancing
the confusion in a difficult area for new users by confusing functions and
special forms in the notes in the manual is hardly a good idea. -- Moon [not done]
{controversial}
100: "environment" => "env". Make the cross reference to *EVAL, not
to EVALHOOK, since EVALHOOK just refers you to *EVAL. -- DLW [done]
101: (Moon's proposal to have a PROCLAIM function and make the DECLARE
magic-syntax not be allowed at top level). [not done]
{controversial}
102: |P 2: 'keyword' -> 'symbol'. Names of declarations are not in the keyword
package, and should not be. [done]
Also this paragraph needs to be made to avoid confusing the reader by making
him think that SPECIAL declarations are not pervasive (explained on the next
page). -- Moon [not done]
{will clarify}
* 102: |P 5: This paragraph is -totally- random. Especially the weird exceptions
('for variables not bound by that form' [although since it is ambiguous which
of the two forms being discussed you are referring to, maybe I just made the
wrong choice of form and this one isn't so weird], 'except for the first
initialization form'). It would make a lot more sense to adopt the following
rule, even though it means that LET isn't a macro that expands into a LAMBDA
combination (unless one with no arguments that uses &AUX as a trick). -- Moon
Code used to compute initial values for bound variables in a
variable-binding special form is included in the scope of pervasive
declarations at the head of the body, in all cases.
Such code does not see non-pervasive declarations
in the body when the scope of the variable binding such a declaration
is attached to does not include that code (of course).
This is much better than forbidding pervasive declarations except for a bunch
of exceptions that you discover you need in order to write programs. [done]
* 103-105: The meaning and scope of global declarations in the Lisp
Machine is unclear. A top-level (declare (optimize ...)) probably wants
to apply only to the file in which it appears, whereas a top level
(declare (special ...)) has to side-effect the global environment and
persist after the file is loaded. -- DLW
{controversial}
* 103: The note about how LOCALLY "cannot be used meaningfully for
declarations of variable bindings" is not completely clear. I first
thought this meant that you couldn't do SPECIAL declarations in LOCALLY
because there are no bindings, but the first example on page 104 does
so. What is this sentence trying to say? -- DLW [done]
103: (under locally) '(optimize' -> '(declare (optimize' -- Moon [done]
103: It should be mentioned in the description of the SPECIAL declaration
form that DEFVAR is the recommended way of declaring a special variable.
--Benson [not done]
{will clarify}
104: 'name' appears spuriously in the ftype equivalent of the function
declaration. -- Moon [done]
* 106: Because of the "declaration" declaration, we must define declarations
to be processed in serial! -- DLW
[gloss] he changed the manual to say that this declaration may only be used
at the top level of a file.
107: I've been burned at least three times tonight by the fact that the
symbol chapter refuses to admit that section 7.1.1 (on value and
function cells) exists. There should be some kind of cross-reference,
since I keep forgetting how to do fsymeval. --Moon [not done]
{will clarify}
* 108: Re the query: I think "it is an error". -- DLW [not done]
{okay by me}
109: 'getf' in wrong font (first word in its description) -- Moon [done]
109: SETF of an entire property list should be strongly discouraged,
since the system itself, or other packages, may be using the property
lists of any symbol. -- DLW [done]
* 109: why wasn't putf flushed when putprop was? -- Moon [not done]
{okay by me}
109: PUTF should be flushed, since (SETF (GETF x y) z) works equally well.
--Benson [not done]
110: symbol-print-name should be called symbol-name. --Moon [not done]
{will fix}
110: The compatibility note about samepnamep on the Lisp machine is false.
I have pointed this out before. -- Moon [done]
* 110: I see nothing to be gained by not defining the order of search in
get-properties. It's not like the implementation is allowed to use a hash
table for a property list, since get-properties takes a place argument
and what the contents of that place can be is strictly specified. It
should be defined to return the property closest to the front of the list
being searched. -- Moon [done]
110: [gloss] Third value of get-properties changed to be like GETL's value.
111: Sec 10.3, in |P 4, "an uninterned symbol prints in the same way as ..."
is not true; it uses #:. (This was pointed out to me by Bob Cassels of
Symbolics; apparently neither Moon nor I caught this.) -- DLW [done]
[Note: package chapter not reviewed since Fahlman's replacement will be installed]
* 115: You need a description here of the concept of a "package name".
Names should be strings, not symbols.
{okay by me}
A more serious question: what is the value of (symbol-package 'car)
allowed or restricted to be? The ploy of saying that making a new
package semantically does a copy looks like it is intended to allow us
to share, but this doesn't really work in the presence of side-effects
on the copied/shared package, which you can get from INTERN and
UNINTERN. EXPORT copying into the USER package, for example, is
really wrong.
I'd like to see a complete example of how a tiny yellow-pages program
would be written, using this facility. I'm not convinced that it
can be done! -- DLW
{It is important to have such an example in the manual, of a full
but small yellow-pages facility, if we can possibly manage it.}
115: Why allow *package* to be bound to a name? This is just extra
complexity and inefficiency for no gain. -- Moon
{okay by me}
117: naming packages with symbols rather than strings cannot work. In what
package is the symbol returned by package-name? It can't always be in the
one the caller expects unless it is global (not shadowed by anyone) or always
referenced with a package prefix (a keyword for instance). Save yourself
a lot of problematic interactions by making them strings. -- Moon
{okay by me}
* 118: The two symbol case of EXPORT, which calls UNINTERN, cannot work
in any system where compiled files intern symbols only once and then look
them up in a table, as is true of most "fasload" schemes. Perhaps this can
be kludged by allowing EXPORT only at top level and having the compiler
kludgily convert the arguments from symbols to strings. This applies to
SHADOW also. Furthermore this whole mechanism will collapse if you try to
add inheritance to it; it is okay as a "clumsy obarray switching" scheme,
but cannot "accomodate experimentation with extensions." Probably the best
thing is to document this as purely an interim kludge, rather than as the
foundation of what Common Lisp will have eventually. -- Moon
Actually, things are much worse than that. By trying to avoid taking a stand
on inheritance, this package system has the worst possible form of inheritance
(namely copying). The fundamental business of a package system is to provide
easy and robust ways of controlling when the same name in two different contexts
gives the same symbol and when it gives two different symbols. By making the
USER package (the one that programs are loaded into by default and typed input
is interned in by default) be the package from which all other packages inherit
(by copying it at the time they are created), the accidental-sharing bug is
maximized: whether two packages share the symbol X or have each their own private
symbol X depends on whether the user happened to type an X before loading those
packages. It isn't reasonable to require a SHADOW declaration in every package
of every symbol other than those that are explicitly imported from the Common
Lisp language itself and from other packages.
By using copying rather than a more dynamic inheritance, the
accidental-shadowing bug is maximized: If package A depends on something
exported by package B, but package A is loaded first, then when package A
copies the user package, package B's exported symbols have not been placed in
the user package yet (unless it happened by coincidence that some third
program, already loaded into the USER package, had interned those symbols).
Thus package A gets its own private symbols by those names. Later, when
package B is loaded, the system has no way of knowing that those symbols in
package A were supposed to have been the same symbols. A related screw is
that because there are all these copies, it is maximally difficult to patch
things up if you discover that you made a mistake; for instance, if you want
to export another symbol from a certain package.
If you consider the example of mutually-recursive modules given on page 292,
there is no way to implement this using the package system, other than by
putting in explicit calls to INTERN to place symbols in other people's packages.
This is basically due to the copying form of inheritance.
A possible way to make this package system workable as an interim substitute
for a "real" package system, with only minor tweaks, is to eliminate the
copying form of inheritance, and instead to use the searching form of
inheritance, adding the notion of each package having two sets of symbols, the
internals and the externals. There cannot be two different symbols with the
same name, one in the internals of a package and one in the externals of the
same package. The EXPORT statement declares the externals, moving symbols
there from the internals. Furthermore it is possible to declare the externals
of a package separately from creating the package and loading code into it,
i.e. separately from doing any INTERN operations, i.e. separately from binding
any names to symbols. INTERN with respect to a certain package searches its
internals and externals, and then searches the externals of all other
packages, including Common Lisp itself (or alternatively, searches a list of
externals defined when the package is created). It is important to note that
this is only a description of functional behavior, not of the implementation.
For example, there are at least two ways of implementing this searching
behavior that do not require INTERN ever to make more than a single hash-table
lookup. Then one must decide the following issues:
- is it an error for more than one package to EXPORT the same symbol,
and if not do they share one symbol or do you get multiple external
symbols with the same name, so that the order of searching externals
of packages in INTERN matters?
- if package A has a symbol FOO in its internals, and inherits from
package B, and then package B exports the symbol FOO, what happens?
And what if there is more than one internal FOO already?
- what syntax and arrangement of files and of compilation do you use
to take advantage of the fact that you can preload the EXPORT statements
of mutually-recursive modules before loading the modules themselves?
- how do package prefixes fit in?
I have not worked out the details of this, so I don't know whether it is
completely workable. However this is a subset of the future Lisp machine
package system plans.
-- Moon (after discussion with Bawden)
119: Missing hypens in resultform. -- DLW
{will fix}
122: (introductory sentence of 12.2) 'signal an error' -> 'are an error'. [done]
The arithmetic primitives should not be required to have run-time error
checking on impotent machines. Also it says they work on all types of
numbers, but most of them do not work on complexes. What values do the
comparison functions return when given only one argument? They should
either require at least two or the boundary-case values, which are
non-obvious, should be given explicitly. -- Moon [done]
123: The definition of (= 3 3.0) should not be hidden in a compatibility
note! Be explicit about this in the main-stream text. -- DLW [not done]
{will clarify}
124: When you talk about "required coercions", you really have to define
just what these coercions are and what the rules are. For example, what
happens when a rational meets a float (presumably you get a float of the
same precision, but this isn't written down anywhere that I can find). -- DLW [not done]
{will clarify}
125: Likewise, the "rules of floating-point contagion" are referred to,
but those rules aren't written up anywhere. -- DLW [not done]
{will clarify}
127: "All produce floating" is not really true: (expt 3 5) surely
produces an integer. Is (log 8 2) => 3 or 3.0? What about (sqrt 4)?
This needs to be more explicit. -- DLW [done]
127: (exp) 'number' should be in italics -- Moon [done]
127: [gloss] (sqrt -9) is explicitly required to return a complex number
(not error). This is probably a loss (we've been through this many,
many times before...)
128: Say explicitly what the phase of a non-complex number is. -- DLW [done]
136: [gloss] remainder has been renamed to rem
137: float-fraction is referred to twice in the text; presumably
this is a typo. -- DLW [done]
137: 'fraction' or 'significand'? Text is inconsistent -- Moon [done]
* 137: You have not provided any way to extract the fraction/significand
of a float as an integer, except perhaps by the kludge of taking NUMERATOR
of RATIONAL, or by taking FLOOR of SCALE-FLOAT of FLOAT-FRACTION by a magic
number. Add a function to do this, and a companion function (or a second
value) to get the corresponding exponent, which differs from FLOAT-EXPONENT
by the magic number. -- Moon [done]
138: Specify that all arguments to these functions must be integers. -- DLW [done]
139: Delete the word commutative, it is irrelevant and furthermore two of
the functions you claim are not commutative in fact are. -- Moon [done]
142: 'byte' appears in italics when it should be bold three times on this page
(the other three times are correct) -- Moon [done]
147: The arguments to - in the Lisp-code definition
of short-float-negative-epsilon in the Laser edition are backwards--Moon [not done]
{will fix}
150: [gloss] standard-charp renamed to standard-char-p
graphic-charp renamed to graphic-char-p
string-charp renamed to string-char-p
alpha-charp renamed to alpha-char-p
uppercasep renamed to upper-case-p
lowercasep renamed to lower-case-p
bothcasep renamed to both-case-p
digit-charp renamed to digit-char-p
150: How is alpha-charp affected by bits and fonts? -- DLW [done]
* 150: Say explicitly how fonts and bits affect alpha-charp and xxxcasep.
It's hard to tell but it appears the intention is that bits must be zero
and any font restriction depends on the implementation. -- Moon [done]
151: 'i' -> 'j' in the example, and 'string-length' -> 'length' -- Moon [done]
152: How is char= affected by bits and fonts? -- DLW [done]
* 155: The effect of char-upcase and char-downcase should be allowed to
depend on the fonts and bits in an implementation-dependent way. For instance,
in the Lisp machine characters with non-zero bits do not have alphabetic case
in the same way that graphic characters do. -- Moon [done]
* 155: The examples for digit-weight call it digit-char. I prefer the
latter name, since what it returns is a character. The name digit-weight
could easily be thought to have the functionality of digit-charp. -- Moon [done]
156: Are the symbols returned by char-name in the keyword package? -- DLW [not done]
{will clarify}
* 156: (char-name) Why are the names symbols, rather than strings? Since
most of the names are implementation-defined it seems unlikely that people
should be encouraged to do EQ testing on character names rather than EQL
testing on character objects. What package are these symbols in? For characters
with bits, does char-name stick on "control-" prefixes, or is there another [done]
function to do that? And how do you tell it whether you want "c-" or "control-"? -- Moon
* 157: why isn't set-char-bit superseded by setf and/or make-char? Is it
because of wanting to change a bit in a character without doing an assignment
of the result? -- Moon
[not done] (but the function is reasonable I guess)
{You guessed it.}
* 160: |P 2: :from-end should be explicitly specified not to guarantee that
the :test function sees the sequence elements in any particular order, such as
the opposite order as it would without :from-end. In general test functions
with side effects should be discouraged. On the other hand, those sequence
functions that take explicit functional arguments (not :test/:key/-if/-if-not)
should allow side-effects in that function and guarantee the order of calls.
This applies to map, some, every, notany, notevery, and reduce. This means
that reduce is the only sequence function where :from-end has a guaranteed
effect on side-effects, rather than just controlling the form of the result.
The manual already guarantees this except that for reduce it is not 100% clear. -- Moon
[done]
162: The second |P under concatenate is nonsense, probably left over from the
days before it took a result-type argument. -- Moon [done]
164: Explaining that the what the reduce function does is to reduce the
sequence is less than illuminating if you've never seen APL; this use
of the word "reduce" is highly specialized jargon. Also, what if the
subsequence has only one element? Give some examples with subsequences
that are one and zero elements long. -- DLW [done]
* 164: Should there be a more concise way to do
(reduce '(lambda (x y) (union x y :test #'pred) seq)
It would be wrong for reduce to pass on unrecognized keywords to the
function, I think, even though that work in this specific case. -- Moon [not done]
{controversial. I don't think this should be addressed. That's what
lambda is for.}
164: (reduce) clarify that if the number of elements (in the sequence and
the initial value) is 1, the function is never called and that one element
is the result. -- Moon [done]
165: |P 1: refers to the ':start' keyword, which replace does not accept -- Moon [done]
* 166: remove-duplicates and delete-duplicates need :key
I think it should be defined by the language whether the first or the last
representative in the sequence of an equivalence class is retained (you can't
tell with the default test, EQL, but in general it makes a difference).
One way to do this is to say that by default it keeps the last representative,
but with the :from-end keyword it keeps the first. Defaulting to the last
might be weird, but it is more consistent with the pseudo-english
"remove-duplicates :from-end". -- Moon [done]
* 166: There should be a way to substitute for subsequences as well as for
single elements as SUBSTITUTE does. --KMP,Moon [not done]
{controversial and hairy}
* 167: nsubstitute may as well guarantee that the result is eq to the argument,
since I can't imagine any implementation in which this would not be true.
(If it was a tree operation rather than a sequence operation, such that it
could replace conses in the backbone of the structure, there would be an issue.) -- Moon
[not done]
{controversial. I see no need for a special-case guarantee here.
Parllelism is more important.}
168: add a note explaining why COUNT accepts a :from-end keyword. -- Moon [done]
168: (BSG's note that maxprefix,maxsuffix,mismatch are redundant)
[done] [not done] [text clarified but there are still all three functions]
169: stable-sort contradicts the statement on p.159 that variants are named
by adding suffixes. But don't rename it! -- Moon [done]
169: 'search-from-end' -> 'search when :from-end is specified' -- Moon [done]
169: it doesn't say what :from-end does for maxprefix and maxsuffix. I could
imagine it transforming one into the other, or I could imagine it merely
contradicting the last paragraph in the description, where it says the order
of matching is undefined. -- Moon [done]
170: |P 1: 'the function k' -> 'the :key argument' -- Moon [done]
170: 'above two expression' -- Moon [done]
170: |P 4: define what it means for the predicate to consider two objects equal,
in case some readers can't figure it out. It's (p x y) = (p y x) = nil. -- Moon [done]
171: (under merge) 'the function k' again -- Moon [done]
171: [gloss] merge has a new first argument, result-type.
174: (tree-equal) it says that equal recursively compares structured objects.
This is only true for strings and bit-vectors according to p.56. -- Moon [done]
175: [gloss] definition of endp fixed to be true of nil and false of conses
(it was backwards, but we didn't notice)
175: [gloss] optional second arg to list-length flushed. Instead it is required
to return nil if the list is circular. [Was this voted on????]
{Not voted on, but the algorithm is so simple that I don't see why we
can't just do it. More than one person commented that he got screwed
by either his program or the system placing too low a limit on the count,
because very long lists were involved.}
177: The second make-list example doesn't work, because the keyword is
missing. -- DLW [done]
177: (make-list) the note about the Lisp machine is false. I believe this is
the third time I have pointed this out. If you have an edition of the Lisp
machine manual whose cover is not gray or blue (i.e. red, or, God forbid,
black) throw it away. Gray and blue are the same except for who you get
it from. -- Moon [done]
178: copy-list should cross-reference copy-tree as well as copy-seq. -- Moon [done]
179: I'd rather not have the language definition mandate that nreconc
must be "more efficient". The wording here ought to say "except that
it is potentially more efficient". -- DLW [done]
179: The :test keyword is missing in the definition of pushnew. -- DLW
179: :test keyword missing from pushnew's heading line -- Moon [half done]
{will fix}
181: |P 1: 'copy the' -> 'copy of the' -- Moon [done]
182: (cross-reference to substitute) 'of sequence' -> 'of a sequence'
Also at the beginning of section 15.4 you should have a reference to
the sequence chapter, as in the beginning of 15.5, since it doesn't
say specifically under each function what :test means and what it defaults to. -- Moon [done]
* 182: does substitution only substitute for leaves (atoms), as the text
seems to say, or does it also substitute for conses, as in the Lisp machine
and Maclisp? -- Moon [done]
182: [gloss] subst is required to make a complete copy of the tree.
I'm not sure I'm happy about this, also nothing is said about whether sublis
makes a copy or not. --Moon
{On the contrary, the second sentence explicitly states that the
result of SUBST may share with the argument tree. Also,
examine the sample code for SUBST. Will clarify SUBLIS.}
185: [gloss] a-lists are specifically allowed to contain nil, and assoc
can't just take car of it, but must specifically ignore it and pass on.
This isn't really new, but was clarified.
{Will add implementation note that one can effectively
do the check outside the inner loop for speed.}
186: equal vs eql for assoc is noted twice -- Moon [done]
189: More S-expressions. This use, in particular, is vague, since the
exact meaning is important but the term S-expression was never defined.
I think the term "tree" is called for here. The same comment applies
to sxhash on p 191. Also, the examples use the puthash ex-function (RIP). [done]
189: puthash appears in examples. |P 4 thinks make-hash-table doesn't make all
kinds, but make-equal-hash-table has been flushed. The introductory sentence
of 16.1 has this problem, too. -- Moon [done]
190: The stuff about "bad luck" was lifted from the Lisp machine manual and applies
only to the particular weird implementation of EQ hash tables currently used there.
It doesn't belong in the Common Lisp manual. Just say "size is a hint to the
implementation how big a table to allocate initially." The default size should
be implementation-dependent, since the tradeoffs that determine what default is
appropriate are implementation-dependent. Under make-hash-table, say what
:test defaults to (presumably EQL). -- Moon [done]
192a: (Moon's proposal to clarify the meaning of "simple vector") [not done]
This proposal can be found in the file P:>common-lisp>simple-vector.proposal
{controversial}
192a: Flush the limitation of array dimensions, ranks, and index offsets
to fixnums. Just say that the limit is implementation-dependent and perhaps
add a note that in some implementations the limit coincides with the
fixnum/bignum boundary. Perhaps specify a minimum required value for the
limit on array dimensions, and specify that the limit on index offsets should
be the same as the limit on array dimensions. This affects pp. 11, 19 also. -- Moon
[not done]
{okay by me}
192b: Say explicitly what the default value of the :adjustable option is.
It looks from the surrounding discussion like it's NIL. -- DLW [done]
192b: The discussion of displaced arrays really is needed here. -- DLW [not done]
{will clarify}
192c: (at the bottom) The statement that make-simple-vector may be
easier for [sic] clearer to use it not well-justified; it looks to me
as if make-array is just as easy to use. Maybe you really mean that
it's good to use this function if you're trying to emphasize the fact
that the thing being produced is a simple vector? -- DLW [done]
* 192c: Is it make-vector or make-simple-vector? I prefer the former, because
it is shorter and because simplicity should be a secondary consideration. What
makes the vector simple is that you didn't use any of the "complex" keywords,
not specifically that it was created with make-vector rather than make-array. -- Moon
[gloss] make-vector uniformly renamed to make-simple-vector
192c: ':type' -> ':element-type' in examples -- Moon [done]
192d: array-element-type needs a cross-reference to subtypep. [done]
192d: array-dimension needs a cross-reference to length (esp. because of
fill-pointers). -- Moon [not done]
{will clarify}
192e: svref and sgvref should cross-reference to page 34 and give the type
expressions for the arguments they accept: (simple-vector * *) and
(simple-vector t *) respectively. -- Moon [done]
192e: Fractured English in the introductory paragraph of 17.4. -- Moon [done]
192f: |P 3, strike the sentence about indefinite number of arguments. -- Moon [done]
192g: fill-pointer itself seems to be missing. -- DLW
[gloss] It says that you use the LENGTH function to access the fill-pointer of an array.
* 192g: flush reset-fill-pointer, add fill-pointer, and allow setf of fill-pointer. -- Moon
[not done]
{controversial}
192h: ':type' -> ':element-type' in adjust-array -- Moon [done]
[not done] [i.e. it's only half done!]
{will fix}
192h: :type should be :element-type in adjust-array. Also, it should
probably say that the result is always :adjustable. Also, the phrase
"could have been created" is confusing; do we mean subtypep? Also, if
you use :fill-pointer t, presumably the fill pointer gets set to the new
array length, not the old one? --DLW [not done]
{will fix}
195: |P 3: 'optional' -> 'keyword'. |P 4: they aren't analogous "respectively"
because 'string-not-lessp' and 'string-not-greaterp' are out of order. I'd [done]
rather see these renamed to 'string-less-or-equalp' and 'string-greater-or-equalp',
not respectively. -- Moon [not done]
{will clarify}
195: There is a reference to STRING<> in the description of STRING-NOT-EQUAL,
which should be changed to STRING/=. --Benson [done]
* 195: string-trim should be specified to not necessarily make a copy, like
string-upcase. I guess it doesn't really make sense to give it :start/:end
arguments, though. -- Moon [done]
* 195: 'trim' is a good idea. Problem is that (TRIM bag seq) should trim from
both ends by default, so you have to use non-standard :FROM-LEFT and :FROM-RIGHT
keywords or something. And should the first argument be a bag or an element?
(If it's an element, you can get the bag effect with TRIM-IF and POSITION, but
that gets somewhat verbose). -- Moon
[gloss] the query was flushed
195: make-string needs a cross-reference to make-array for non-simple case. -- Moon [done]
197: if (string x) <=> (coerce x 'string) exactly, say so. Both of these
should coerce a character into a 1-element string; neither says so now. The
old argument against this, that people might expect string of a number to give
the decimal encoding of that number, no longer applies now that characters are
not numbers. -- Moon [done]
197: [gloss] string is required to signal an error if its argument is not a
string and not a symbol. This is wrong; it should convert a character to a
one-character string. Also it says that string will not convert a sequence of
characters into a string, but coerce will. This might be all right, except
under coerce it says that when coercing to a string the implementation is
allowed to return a more general type. It isn't clear if this is just a
poorly-phrased reference to the fact that make-array with an element-type
specified will return whatever array type is actually implemented that best
fits that element-type (in which case coerce to a string would return a string
since all implementations have strings), or whether this really is intended to
give the implementation freedom to do anything. Also the coerce writeup
doesn't say anything for or against coercing from a character to a 1-long string.
{controversial}
{will clarify}
* 203: I agree with Bawden's suggestion for revision of defstruct slot options -- Moon
[not done]
{okay by me}
204: |P 2: defstruct options are not in the same format as slot options -- Moon [not done]
{will fix}
* 204: How does defstruct create named vectors (second to last paragraph)
if neither make-array nor make-simple-vector takes a :named keyword? It would
be nice for defstruct to be written entirely in the portable language, not
in some magic implementation-dependent language. -- Moon [not done]
{controversial. Make a proposal? Is make-array the right place to
do this?}
205: constructors and predicates are specified as being in the same package
as the structure name. This is undesirable in the presence of package
inheritance. Specify that these names are interned in the package that is
the value of *package* when the defstruct macro is expanded. -- Moon [not done]
{will fix}
* 210: include applyhook as recently added to the Lisp machine. It's a third
argument to EVALHOOK, which is a function that gets called with the same arguments
as APPLY when EVAL is about to APPLY after evaluating arguments. This does not
intercept any other function calling in the interpreter, such as the one in
MAPCAR. The second argument to the applyhook is like an &rest argument in
extent (i.e. don't save it and also don't side-effect it). Either of the
two hook functions given to EVALHOOK may be NIL if you only need the other
one. Both hooks are disabled (bound to NIL) when either hook is invoked.
Longer explanation in the Release 4.0 release notes. -- Moon [not done]
{okay by me}
211: What does constantp do with a list whose car is QUOTE? -- DLW [done]
* 211: (constantp ''foo) -> t or nil? There are arguments in both directions. -- Moon [done]
[gloss] nil "because it does not evaluate to itself". This is, of course,
quite bogus since the symbol pi doesn't evaluate to itself either.
{Oooops. Chalk one up for muddy thinking. Okay, controversial.
I now favor (constantp ''foo) => T.}
* 212: When no values are returned, /, //, ///, *, **, and *** should not
be advanced, since nothing was printed. Likewise when execution is
aborted, they should not be advanced. Of course when printing is aborted
they should advance. Since these variables are for people, not for
programs, it is more important that * be the last thing that was printed
than that + and * be kept in sync. -- Moon [not done]
{controversial. I disagree -- parallelism is important, and I think that
/, //, /// should always advance.}
213: More S-expressions. -- DLW [done]
214: the with-open-stream special form of the Lisp machine is useful for
the same reasons as with-open-file. (with-open-stream (var maker) body...).
maker is a form that returns a stream; var is bound to it. -- Moon [not done]
{okay by me}
* 214: Add *debug-io*, for debugger interaction. It is rare, but not unknown,
for this to be different from *query-io*. -- Moon [done]
215: 'characters the substring' in make-string-input-string -- Moon [done]
216: the with-input-from-string example assumes that ? is alphabetic,
although it is reserved for the user, has the wrong value for j (it is
actually set to 11), and doesn't exhibit the common case where the :start
and :index keywords are the same (you have a variable containing the "current"
index into the string and you want it advanced). -- Moon [done]
[new] The text claims it exhibits the case where :start and :index are
the same, but it doesn't actually.
{will fix}
217: It's pretty strange that the "operations on streams" section does not
include input or output. I guess it is desirable to put the read-char
function near the read function, but you should either break up the huge
I/O chapter more or put in a cross-reference. -- Moon [done]
220: |P 2: closures are mentioned but have been flushed -- Moon [done]
220: (compatibility note) 'porvided' -- Moon [done]
220: |P 2: 'reader LISP' -- Moon [done]
221: |P 5: "dot context error" will not catch prinlength cutoff, since it
prints 3 dots. Or does it put spaces between them? -- Moon [not done]
{The new discussion of symbols in the data types chapter specified
that any token consisting entirely of periods is syntactically illegal
with the exception of a single-dot token in a place appropriate
for dot notation.}
* 221: where did IBASE go? -- Moon [not done]
{controversial}
221: using symbols as package names can't work; see my other comments. -- Moon
* 222: (table 21-1) # is a non-terminating macro character in the Lisp
machine now. If Common Lisp is going to have them, # should be one. -- Moon [not done]
{controversial}
223: (table 21-2) why are the upper and lower case exponent markers
not in the same order? Also right below this table there are spurious
references to table 22-3 (should be 21-3). -- Moon [done]
225: caseq used in an example -- Moon [done]
226: assq used in an example -- Moon [done]
228: the example of `#( calls make-simple-vector (which I think should
be called make-vector) with nil for the length. -- Moon [done]
230: (table 21-4) backspace appears twice, #: is undefined -- Moon [done]
231: The comment about #/ in the Lisp machine accepting both syntaxes is
false. -- Moon [done]
* 232: #. and #, have nothing whatever to do with quote. The way it's
written is confused and confusing (I admit it is probably my fault). You
mean to say "This allows you to include in an expression complex objects
that do not have a readable printed representation." -- Moon [done]
232: (under #,) 'unless unless the compiler' -- Moon [done]
232: 'too many bit are' -- Moon [done]
233: #nAform shouldn't use the word "form", since it's not a form at all
although you might think it would be. -- DLW [done]
233: '##' -> '#n#' since n isn't optional -- Moon [done]
233: The easiest way to make the ## example work is to change both
x's in the last line to y's. -- DLW [done]
* 233: (#=) It says the scope is "the outermost call to READ". Interaction
between recursive calls to READ is certainly mysterious. Probably there is
a kludge in BREAK to prevent the next READ from thinking it is called recursively.
I'd rather see a different function for macro-character functions that want
to read sub-expressions to call. This would unfortunately imply that
READ-DELIMITED-LIST is illegal for anything but a macro-character to call,
since it has to know which version of READ to use. If we don't add a separate
function, this mysteriosity should be carefully documented. -- Moon [not done]
{hard. I think a separate function will be needed. Alternatively,
how about an extra keyword :recursive to the input functions READ,
READ-PRESERVING-WHITESPACE, and READ-DELIMITED-LIST, which when
true specifies that a new ## scope is not to be made?}
233: is n optional in #nA ? -- Moon [done]
234: [gloss] #|...|# (as in ZL) added.
235: 'readtable' -> '*readtable*' in the example of restoring the readtable -- Moon [done]
235: In the copy-readtable example, the NIL isn't needed since that
argument is optional. -- DLW [done]
237: What do get-dispatch-macro-char and set-dispatch-macro-char do if the
disp-char is not actually a dispatch character? I will assume that they
signal an error, but that get- returns NIL if disp-char is a dispatch
char and sub-char is not defined. -DLW [not done]
{will clarify}
* 238: Can we find less barfucious names for the printer control variables?
The original motivation for these names, Maclisp compatibility for PRINLEVEL
and PRINLENGTH, went away when the stars were added. -- Moon [not done]
{controversial}
238: don't mix the variable descriptions into the middle of the text, it's [done]
extremely confusion, especially when the variable descriptions are incomplete
but appear before the text giving the real story. Move all the variable descriptions
to the beginning or the end, and make them complete or make them not break down
by data type at all. E.g. *prinescape* tells you about symbols but not strings. -- Moon
238: Another S-expression in *prinescape*, first line. -- DLW
{will fix}
238: There should be the equivalent of SI:PRINT-READABLY, which if true causes the
printer to signal an error rather than printing something that READ cannot
understand. (E.g. #<, prinlevel cutoff) -- Moon [not done]
{Another printer variable?}
239: (symbols) 'the only characters' -> 'only the characters' -- Moon [done]
* 239: Where did *ibase* go? -- DLW
{controversial}
240: Say explicitly what the default value of *princase* is. -- DLW [done]
240: (#:) there are some applications for which it is desirable to print
uninterned symbols as if they were interned -- provide a separate flag
to control the use of #:. [done]
240: (last line) 'close parenthesis "("' -- Moon
{will fix}
* 240: I think not allowing a package prefix before a vertical-barred symbol
is a dead loss. This affects page 226 (where vertical bar is described)
also. -- Moon
{controversial}
241: S-expression on first line. -- DLW
{will fix}
241: In the description of how to print arrays, I think you have left
and right confused. -- DLW
{No, I think it is correct. Examine it carefully.}
241: The DEFSTRUCT description refers to a :PRINT-FUNCTION option, while the
PRINT description refers to a :PRINTER option for DESTRUCT. The former
is correct. --Bawden,Benson [not done]
{will fix}
* 242: What is the defauly value of *prinarray*? -- DLW [done]
242: In the examples under *prinlevel*, the example where v=3 and n=2 is incorrect.
It says (if (member x items) ...). It should say (if (member x ...) ...). --DLW [not done]
{will fix}
* 243: nil and t as streams are silly. It's not as if the rest of the language
was Maclisp-compatible at this level of detail. -- Moon [done]
243: |P 3: 'see the end-of-file act according' -- Moon [done]
243: Making READ-PRESERVING-WHITESPACE a function rather than a special
variable you bind around a call to READ is nice. However, it brings
up the same problem with recursive calls to READ as #= does (my comment
about that, extracted from my general Laser-edition comments, is enclosed
for reference). Suppose you do (READ-PRESERVING-WHITESPACE)'FOO<space>;
that should preserve the space just as if there were no quote. But if
the quote macro character is defined the way it is in the example on
page 236, this won't happen; the inner call to READ will swallow the space.
If the quote macro character isn't really defined that way, and that is
just an oversimplified pedagogical example, then how are users supposed to
define their own macros? I think the old Maclisp "TYIMAN" family of crocks
are still with us.--Moon [not done]
{Regarding the proposal for a :recursive keyword to READ, perhaps
it would also when true cause the "global preserve-whitespace flag"
not to be altered.}
244: peek-char is used in an example with incorrect arguments -- Moon [done]
245: |P 2: (read-delimited-list) 'eof-value' -> 'eof-errorp' -- Moon [done]
245: The way read-line is expressed, it takes an input-stream. However,
the classic readline function echoes what it is doing and provides the user
with rubout handling. Similarly, read-char takes an input stream, but the
classic tyi function does echo. I think these functions should be defined
to do echoing on interactive streams; if not, we'll have to introduce
new ones that do. -- DLW [not done]
245: Does read-char echo on interactive streams? (Probably the answer
is "yes".) --DLW [not done]
{Sigh. Previously there was text to the effect that echoing is done
and people barfed at me. I think they were right at that time:
echoing is a property of the stream, or the interaction of the stream
and the function, not solely of the function.}
246: |P 6: 'involved, when clear-input' -> 'involved, then clear-input' -- Moon [done]
246: |P 3: peek-char should not say anything about echoing, since read
and read-char do not. -- Moon [done]
246: |P 5: 'these functions' -> 'read-char-no-hang' twice. -- Moon [done]
* 246: read-from-string cries out for &key arguments -- Moon [done]
* 247: parse-number cries out for &key arguments. Also returning 0 for a
null string is totally random. The Lisp machine function by that name
returns NIL in this case (assuming fail-if-not-whole-string is the same
argument as no-junk-allowed) -- Moon [done]
* 247: In parse-number, we should seriously consider changing the default
value of no-junk-allowed. -- DLW
It should be renamed to junk-allowed, and the default should still be NIL.
Thus the default should be to err if funny characters are seen. -- Moon
If you aren't receiving the second value, you shouldn't have to specify the
optional argument. If you are receiving the second value, you shouldn't
mind specifying the optional argument. Thus erring should be the default. [done]
-- MMcM (paraphrased by Moon)
248: print is defined to output a <return>, whereas terpri is
defined to do "whatever is appropriate", maybe a return-linefeed,
whatever. In other words, the spec is not clear about how to handle the
fact that some systems use CRLF and others use CR and other use LF. --DLW [not done]
{will clarify}
248: What does the write function return? -- DLW [done]
248: A minor point: PPRINT probably should not return its argument, in order
to be useful when called from a READ-EVAL-PRINT loop. Otherwise the
prettyprinted form tends to get scrolled off the screen by the
"standard" printed return value. This recommendation is made on the
basis of practical experience! Have it return T or NIL or some other
benign object instead. --Benson [not done]
{will fix. Similar argument as for APROPOS.}
249: What do write-string and write-line return? Similarly for the rest of
the output functions. It's fine with me if they are all defined to return
nil, but we should say explicitly. -- DLW [done]
249: the first example on p. 249 should say "princ", not "prin1". --DLW [not done]
{will fix}
251: A string with a fill-pointer is valuable as a format destination. -- Moon [done]
251: |P 1: 'arguments' or 'args' ? -- Moon [done]
252: Not having acquired my black belt in formatting, I didn't try
to verify the examples of format; somebody really ought to try
to run them in a Common Lisp or reasonable facsimile. -- DLW
252: nonexistent function 'control' used in an example -- Moon [done]
* 252: ~:A and ~:S should only affect the printing of NIL given directly
as an argument, not the printing of NILs inside a printed list. This is
because these are for printing an object that is known to be a list, not
for printing data so it can be read compatibly into a N.I.L system. -- Moon [not done]
{controversial}
253: (the query) No, I don't think it's what we want. -- DLW
254: (the query) Yes, I agree. The present formats are completely
random. Also ~$ is really nearly always what you want: this should
definitely be added. It's very important that you be able to control
exactly how many digits you get and how much space is occupied. -- DLW
254: [gloss] ~E and ~F deleted. But ~$ not put in.
254: (under ~&) 'a :fresh-line operation', but Common Lisp doesn't have
message-passing -- Moon [done]
254: random 'fi' in the second |P under ~C. -- Moon [done]
* 254: ~$ is highly useful and should be put in. Pending a concrete proposal,
I think Fortran ~E, ~F, ~G should be put in. I just looked at a Fortran
manual and they look reasonable, except that 1P should be the default scale
for E and G formats. ~$ is close to ~F but not identical, it would seem. I
doubt that anyone would mind changing "absolute goto" from ~G to ~@*. -- Moon
{controversial. I strongly urge the adoption of FORTRAN-like
floating-point formatting.}
* 255: (~T) There is an issue of what ~T should do if you are already in [not done]
exactly the column that is the goal. It could be defined to stay there,
or it could be defined to always output some whitespace. The Common Lisp
manual needs to say which. Here is how it is currently defined in the Lisp
machine, which was the result of some discussion. This is not in the manual. -- Moon
~m,nT n>0 always outputs at least one space
n=0 doesn't move if current position >= desired position
{okay by me}
256: (under '~(') '~;' -> '~' 3 times -- Moon [done]
256: [gloss] Third form of ~[, case-clause with explicit tags, has been removed.
257: ('~@[' example) 'prinlevel' -> '*prinlevel*', 'prinlength' -> '*prinlength*' -- Moon
{will fix}
258: funcall* used in an example -- Moon [done]
258: The phrasing of the "format-error" example was OK in the Lisp
Machine Manual, but in this manual one might wonder whether the
C.L. implementor is required to implement "format-error". You
could just rephrase to say "an implementor might happen to do the
following". -- DLW [not done]
{will clarify}
* 261: We recently changed the Lisp machine so that y-or-n-p always prints
"(Y or N)" after the message. I have no opinion about whether this is an
improvement. -- Moon [not done]
{controversial}
{okay by me}
261: The Lisp machine y-or-n-p types a (Y or N) after the prompt, and
yes-or-no-p types (Yes or No). This helps make the user interface more
uniform, and lets you know which kind of question you're being asked.
C.L. should work this way too. -- DLW [not done]
261: yes-or-no-p: The sentence "It is intended" doesn't come out right;
after all, it doesn't take much thought to type "yes <return>". I
know what you're trying to say but it needs to be rephrased. -- DLW [not done]
{will clarify}
265: type and version can be :unspecific on hosts like ITS, Unix, and Multics
that don't fit the pathname model exactly. The writeup on this in the Release
4.0 notes is good; remind us to send Steele a copy. -- Moon [not done]
{socket to me!}
266: truename of a stream should be a special case, returning the truename
of the file actually open, rather than first converting the stream to a pathname
and then taking truename of that (which can return a different answer). In
some implementations (e.g. ITS) truename of an output stream cannot return the
right answer until it is closed, because the version number isn't decided
until then. I don't have an answer for the query, except to provide some
data. In the Lisp machine, the PROBEF function returns NIL if the file does
not exist, but signals an error if there is an error accessing it, including
no such directory. On the other hand the :TRUENAME message currently returns
NIL for any FILE-OPERATION-FAILURE (this includes directory not found, access
violation, and the like, but not host down or not available). -- Moon [not done]
{will clarify}
267: parse-namestring cries out for keyword arguments. [not done]
{will fix}
Also change ':unspecific' to 'nil' in the paragraph about empty strings. -- Moon [done]
* 267: It looks like host names are followed by two colons. As far as I
can tell the text doesn't say anything about this; you only see it in the
examples. This is incompatible with Lisp Machine Lisp and is likely to
cause problems. On the other hand, it also fixes some problems. [Dave,
I think we have to talk about this.] -- DLW
[In the middle of page 266 it says that namestring syntax is implementation-dependent
and double colon for the host is used purely for purposes of examples. So
I don't think there is an issue. Of course, if logical pathnames are not
flushed then the namestring syntax cannot be implementation-dependent and
so there is an issue again. --Moon] [not done]
{controversial}
* 268: Rename merge-pathname-defaults to merge-pathnames and delete the
default-type argument (more :unspecific braindamage inherited from the Lisp
machine). Or keep it, but change the default value for the default-type to
the type of the defaults. -- Moon [not done]
{controversial}
268: Remove merge-pathname-default and replace it with merge-pathnames; see
the Release 4.0 Release Notes. The default-type argument is completely
wrong, although it took us long enough to find out. -- DLW
[I disagree with this; the thing that is wrong about the default-type
argument is not that it is there, but that it is -optional-. However
merge-pathnames is much more useful and Common Lisp might not bother with
merge-pathname-defaults. --Moon] [not done]
{controversial}
268: [gloss] default-type in merge-pathname-defaults defaults to NIL
instead of :UNSPECIFIC. Still wrong, it shouldn't be an optional
argument at all.
269: 'namelist' -> 'pathname' -- Moon [not done]
{will fix}
270: The merging rules should not include default-type, which turns out
to be completely wrong. Only default-version exists; types are defaulted
just in the obvious way. -- DLW [not done]
* 272: logical pathnames are totally useless if their namestrings aren't portable! -- Moon
[not done]
{controversial}
273: ':type' -> ':element-type' -- Moon [not done]
{will fix}
275: :overwrite should specify explicitly that it does NOT truncate the
file when the file is opened; if you want that, use :supersede. -- DLW [not done]
{will clarify}
275: :supersede's explanation says to supersede the file, which is
not very clear. It sounds like :new-version. The point is that
it is as if you make a new file with the same name as the old file,
and delete the old file when the new one is closed. -- DLW [not done]
{will clarify}
276: The "bindspec" in with-open-file's definition line is bogus. The
definition line should say (with-open-file (stream filename . options) {form}*.
As I keep saying, macros should have destructuring and functions should
not and attempting to introduce an analogy between these things is a mistake.
-- DLW [not done]
{will fix}
276: The error-p arguments to rename-file and delete-file probably come
from the Lisp Machine, where they are considered obsolete. They should
not exist for the same reason car doesn't have an error-p argument. -- DLW [not done]
{okay by me}
276: flush error-p argument to rename-file, etc. It is wrong. These functions
should signal their errors the same way as all other functions, and the same
mechanisms should be used to catch the errors when desired. -- Moon [not done]
{okay by me}
277: (file-length) 'position' -> 'length' -- Moon [not done]
{will fix}
279: For directory, specify that if a wildcard name is given and no
names match, it's not an error; directory returns the empty list. This
may seem obvious but based on our experience it deserves to be
documented. Also, if you give directory the name of a non-existent
file, it should return nil. As for non-existent directories, there has
been a running debate at Symbolics; one theory is that if you give it a
wilcard directory that doesn't match, return NIL, but if you give a
specific directory that does not exist, signal an error. You may not
want to go into this in full detail. Also, directory should not list
deleted files. We are going to have to upward-compatibly extend
directory by adding keyword arguments such as :deleted, so you may want
to put this into the definition in the first place and say that the
keywords are implementation dependent, although you might want to just
leave this open. -- DLW [not done]
{will clarify}
[Changes here not reviewed, assuming Moon's new proposal will be incorporated]
281: See general comments about the error system at the end of this file. -- DLW
282: I think condition-psetq is useless, although I could be wrong. Could
we leave this out until we have some evidence that it's good for anything? -- DLW
289: [gloss] BREAK added to chapter 24, I presume it will be flushed when
it is added to chapter 23 via Moon's new proposal.
{right}
289: First |P under compile: delete 'or select expression'
Second |P under compile: 'If name is a symbol' -> 'If name is a non-nil symbol' -- Moon
[not done]
{will clarify}
290: Second |P under compile-file: ':output' -> ':output-file' -- Moon [not done]
{will clarify}
291: Say explicitly in the second |P of require's description that the
pathname argument is optional if the module is semi-standard or in a
well-known place, and the way this works is implementation-dependent,
but the intention is that the system finds yellow-pages modules for you
without your having to know anything about pathnames. -- DLW [not done]
{will clarify}
* 294: apropos should return a list of the symbols found; this can be quite useful.
RMS recently changed his apropos to take arguments [not done]
string &key package superiors inferiors dont-print predicate
Common Lisp might want to adopt something like this, with perhaps keywords
to filter to only variables, only functions. -- Moon
{controversial. Keywords look okay. There is the same problem as with
PPRINT: after the nice-looking stuff has been printed, do you want your
screen garbaged up with the returned list?}
296: |P 2: dont say 'iff' -- Moon [not done]
{will fix}
297: (rationale) 'mnachine' -- Moon [not done]
{will fix}
* 298: host-software-type and host-software-version should not include the word
'host' in their names, since 'host' means something to do with networks. Perhaps
you want machine-hardware-type and machine-software-type, if 'machine' is the
substrate that supports 'lisp-implementation'. Also the documentation of
host-software-version accidentally documents lisp-implementation-version instead. -- Moon
[not done]
{will clarify}
* 298: In what package are the symbols that are elements of *features*? The
Lisp machine uses keywords currently, but compatibility is not an issue here
since the way you get to the list is different. -- Moon [not done]
{controversial}
--------
Major issues:
1. The rules for scoping of declarations need to be documented more clearly,
and may have real problems as well.
2. The package system contains fatal flaws. (See comments above)
3. The rules of numeric coercion need to be described explicitly. This
may not be a real issue once we know what they are. This relates to
Bawden's comments about Gaussian rationals as well. [not done]
4. What is the policy on dotted lists as sequences?
[gloss] The policy seems to be no policy, i.e. it says that the implementation
is allowed to choose whether or not to "behave reasonably"
{It "is an error" to use a dotted list as a sequence.}
5. The attempt to minimize the number of special forms is seriously flawed.
This is really part of the more general issue that many primitives are missing
from the language; thus many portions of Common Lisp that could otherwise be
written in a portable fashion cannot be, because primitives are missing. This
applies both to "modules" like defstruct, and to special forms as macros, when
there is nothing reasonable for them to expand into. The issue is not only
easing the work of implementation by permitting sharing of perhaps-inefficient
portable code, but also making it possible for users to customize things or
to experiment with language extensions without having to leave the Common Lisp
language. This is probably an issue for the longer term. [not done]
6. Examples are important in a manual, and their accuracy is important since
people will often read the examples and ignore the text. There should be
more examples, preferably an example of every case of every function, with
obvious redundancies removed (do not need to illustrate all possible
combinations of keywords for each sequence function!). Before the manual is
published as a real-world book, all examples should be tested (without being
retyped by a human being) if it is at all possible to find an implementation.
There should also be more cross-references between related features that
are in different chapters. [not done]
7. The error system is completely incompatible with ours. I would feel
bad if we had to move our new error system off to functions with
inferior names so that "signal" and "error" can refer to the Common Lisp
versions; in fact, implementing both error systems in the Lisp Machine
would be hard to do and might result in inefficiencies that we won't
want to have to put up with. This is a severe problem and I don't know
what we should do about it. -- DLW
I thought we agreed in August to prune the error system to just the functions
for signalling errors, and defer providing ways to handle errors (presumably
until the rest of the world agrees that the NES is the way to go, or until
there is enough experience with it to reveal what is really right.) I will
be upset if Common Lisp contains a kludge error system which we know from
experience is wrong and have just spent several months flushing from the
Lisp machine. As RMS has shown, the NES doesn't -really- require flavors,
although of course the second version of Common Lisp will include flavors.
Among the functions and special forms in chapter 23 only FERROR
(with no condition-name argument, a la NES), ASSERT, CHECK-TYPE would be
retained. FSIGNAL (from the Lisp machine) might be added as a minimal
mechanism for proceedable errors. The Maclisp-compatibility case of the
ERROR function might be added, although FERROR is probably always preferred
(in retrospect we should have ignored compatibility and used the name
ERROR for what is now FERROR). -- Moon
-------